// Load all required engine components
Engine.include("/rendercontexts/context.canvascontext.js");
Engine.include("/engine/engine.mathprimitives.js");
Engine.include("/engine/engine.math2d.js");
Engine.include("/engine/engine.object2d.js");

// Load the game objects
Game.load("/initArea.js");
Game.load("/unsafeArea.js");
Game.load("/goalArea.js");
Game.load("/crosshairs.js");
Game.load("/gameObject.js");

Engine.initObject("Nonlinear", "Game", function(){
    
    /**
    * @class Nonlinear: 
    */
    var Nonlinear = Game.extend({
	
	constructor: null,
	
	// The rendering context
	renderContext: null,
	
	// Engine frames per second
	engineFPS: 30,
	// The simulation timestep
	timestep: 0.01,
	
	// The play field
	fieldBox: null,
	xmin: -0.5,
	xmax: 2.5,
	ymin: -0.5,
	ymax: 2.5,
	fieldWidth: null,
	fieldHeight: null,
	pixelWidth: 480,
	pixelHeight: 480,
	position: null,
	scaleX: null,
	scaleY: null,
	
	/**
       * Called to set up the game, download any resources, and initialize
       * the game to its running state.
       */
	setup: function(){
            // Set the FPS of the game
            Engine.setFPS(this.engineFPS);

	    $("#loading").remove();

	    // @DEBUG Show the metrics window while designing
	    Engine.showMetrics()
	    
            // Create the render context
	    this.fieldWidth = this.xmax - this.xmin;
	    this.fieldHeight = this.ymax - this.ymin;
            this.fieldBox = Rectangle2D.create(
		this.xmin, this.ymin, this.fieldWidth, this.fieldHeight);
            this.renderContext = CanvasContext.create(
		"Playfield", this.pixelWidth, this.pixelHeight);
            this.renderContext.setBackgroundColor("#f0f0f0");
	    
	    // Scale the fieldBox to the size of the viewport on the screen
	    // The negative sign causes y to increase going up the screen
	    // rather than down, as is normal in computer graphics
	    this.scaleX = this.pixelWidth/this.fieldWidth;
	    this.scaleY = -this.pixelHeight/this.fieldHeight;
	    this.renderContext.setScale(this.scaleX, this.scaleY);
	    	
	    // Shift the field so that [xmin, xmax, ymin, ymax] is shown
	    // The -fieldHeight is needed because the negative sign above
	    // flipped the field vertically about the top edge.
	    this.position = Point2D.create(
		    -this.xmin, -this.ymin - this.fieldHeight);
	    this.renderContext.setPosition(this.position);
	    
	    // Tell the renderer to update the entire field
	    this.renderContext.setViewport(this.fieldBox)
	    
            // Add the new rendering context to the default engine context
            Engine.getDefaultContext().add(this.renderContext);
	    
	    // Create the game object and add it to the render context.
	    // It'll start animating immediately.
	    var IA = InitArea.create();
	    this.renderContext.add(IA);
	    this.renderContext.add(UnsafeArea.create());
	    this.renderContext.add(GoalArea.create());
	    var shape = IA.getShape();
	    this.renderContext.add(Crosshairs.create(IA.getShape()));
	},
	
	/**
       * Called when a game is being shut down to allow it to clean up
       * any objects, remove event handlers, destroy the rendering context, etc.
       */
	teardown: function(){
            this.renderContext.destroy();
	},
	
	/**
       * Return a reference to the render context
       */
	getRenderContext: function(){
            return this.renderContext;
	},
	
	/**
       * Return a reference to the playfield box
       */
	getFieldBox: function() {
            return this.fieldBox;
	},

	/**
       * Return a reference to the timestep
       */
	getTimestep: function() {
            return this.timestep;
	},
	
	/**
        * Takes in a pixel-valued location on the screen and returns the 
        * coordinates of the point in the game world.
        */
	pixel2coordinate: function(point){
	    //TODO: the mouse coordinate is taken from the upper left hand
	    // corner of the browser screen. I need to shift this to be the
	    // relative position for the upper left hand corner of the 
	    // game screen.
	    var bb = this.renderContext.getSurface();
	    point = Point2D.create(point.x / this.scaleX,
				   point.y / this.scaleY);
	    point.sub(this.position);
	    return point;

	    // Debugging Code
	    // Engine.addMetric("mouseposx", point.x.toFixed(2), false, "#");
	    // Engine.addMetric("mouseposy", point.y.toFixed(2), false, "#");
	    // Engine.addMetric("posY", 
	    //                   this.renderContext.getPosition().y,
	    // 		     false, "#");
	}
    });
    
    return Nonlinear;
    
});